Jumbo frames
環境やスイッチの性能にも依存するが、10GBASE-T回線の性能が6~7Gbps程度で頭打ちになることが多い。その理由はMTU(Maximum Transmission Unit)である。 MTUは、要するに最大フレーム長で、この数字を超えるデータを転送する場合はフレームが分割される。
Ethernetでは最大フレーム長が1500ということになっているので、デフォルトでは1500Bytesを超えるデータは、複数フレームに分割して転送が行われる形になる。
正確に言えば、IEEE 802.3ではMTUは64~1518Bytesと定められている。
ただ、このうち18Bytesはヘッダ領域用なので、データとしての最大値は1500となるわけだ。
MTUは1500Bytesできたが、速度が速くなると相対的にオーバーヘッドが増える
MTUが1500に設定されたのはIEEE 802.3、つまり10BASE-2/5の時代の話である。
その後、IEEE 802.1ad(Provider Bridge)用に8Bytes増やしたり、あるいはIEEE 802.1Q(VLAN)用に4Bytes増やしたり、と細かく増えた規格は存在するが、やはり一般には、1500Bytesのままで現在に至っている。なので、このフレームサイズのまま速度を上げてゆくと、フレーム数が非常に増えてしまい、オーバーヘッドの増加に繋がる点が問題になる。
これはCPUの進化で問題にならなかった
実は、このMTUサイズの小ささは、光ケーブル向けのGbE規格である1000BASE-SXなどで最初に問題となった。以下のグラフは2009年のものだが、MTUを1500Bytesのままにしたときには、スループットが400Mbps止まりでCPUの負荷率が100%に達してしまうという結果になっている。理由は扱うべきデータ量が増えたことで、CPUのフレーム処理が間に合わなくなってしまうためだった。
これがあまり問題になっていないのは、急速なCPU性能の向上のおかげである。
ラフに言えば、現在のCPUは当時の10倍程度は高速であり、もはや1Gbpsのフレーム処理程度でCPU負荷が100%になることはない。
しかし10GbEでこの問題が再発する
MTUを大きくすれば良い(これをJumbo frameという)が、これは仕様が決まっていないので未対応な機器がたくさんある
やる場合は9000ぐらいにしていることが多いらしい
未対応な機器がMTU1500以上のパケットを受け取ると、処理できない
実際はルーターやプリンターなど、さまざまな機器が繋がっており、これらのほとんどは1500までのMTUにしか対応していない。あるいはWi-Fiなどで繋がる機器も同様だ。これらが全部繋げなくなる、というのも困ったものである。
つまりネットワークの中にJumbo frameを出すやつが混在すると困る
対処法はセグメントを分けること
一番簡単なのはネットワークを分割することだ。以下の図のように、通常のMTUとJumbo Frameでセグメントを分割してしまえばいい。従来のネットワークには引き続きMTUを1500に設定した1000BASE-Tで接続し、これとは別に新たに10GBASE-Tのネットワークを追加する、という形になる。この10GBASE-Tの方では、MTUに9000程度の値を設定すればいい。 この場合、サーバーと10GBASE-T搭載クライアントはIPアドレスを2つ持つ形になるので、Windowsのネットワークを使っていると、名前解決にちょっと面倒な場合がある(ブラウズマスターホストがどこに置かれるか次第ではあるのだが、無条件で1000BASE-TのIPアドレスが指定されてしまい、10GBASE-Tが利用されないことが考えられる。というか、昔やったときにそうなった)のだが、これはルーティングテーブルの設定やhostsファイルの追加など、いくつかのテクニックを使えば解決できる。逆に言えば、このあたりがまだちょっと面倒、ということだ。
ネットワークのセグメント分割ってどうやるの?
MTUが異なる機器同士でもTCPのハンドシェイクで小さい方に合わせるようになっているので、2つの機器の間では問題が起きない しかし中間にジャンボフレームに対応していない機器が混在しているとトラブルが起きる
ところでこの仕組みは常に有効かというと、そうでないことに気付くだろう。TCPのコネクション開始時のネゴシエーションは、エンド・トゥ・エンドで行われる。つまり2台のジャンボ・フレームをサポートしたコンピュータが複数のハブを経由して接続されていて(略)間にジャンボ・フレームをサポートしていないハブがあったとしても、このネゴシエーションは成立するのである。3ウェイ・ハンドシェイクのパケットは60bytes弱と小さく、ジャンボ・フレーム通信は必要ないからだ。
だがこの状態でTCPの実際の通信を開始すると、途中のハブでジャンボ・フレームが破棄されてしまうことになる。こうなると、TCPのコネクションはつながったが、ジャンボ・フレームを使った通信ができないという状態になる(送信したジャンボ・フレームに対するACK応答がまったく返ってこない)。これは問題である。ただし通常の小さいフレームは通信できる。
このような場合の対処方法はTCP/IPの実装依存になるが、例えばWindows OSではMTUサイズを以後は576にして、再送する、というふうに動作している(576は規格で要請されているMTUの最小保証値)。これにより、まったく通信できなくなるという事態は回避できるが、ジャンボ・フレームどころか、通常のイーサネットのフル・サイズのパケットすらも使わないので、通信のパフォーマンスはあまりよくない。だからこのような事態が生じないように、ジャンボ・フレームのセグメントは、同一セグメント内では1つだけになるように運用するべきである。
適切に設定しないとパフォーマンスが何もしないより落ちる
Jumbo Frame を使用するには、通信を行うパソコン(LAN アダプター)とそのネットワーク内のすべてのスイッチングハブがJumboFrame に対応している必要があります。
Macでは使えない?
SSD×4台でRAID 0を構築した。MTUは標準の1500バイト、ジャンボフレームの9000バイトをPC、NAS両方に設定し、全ての組み合わせを測定した。
結果はシーケンシャルリードで大きな差が出て、一方でも1500バイトだと650MB/秒程度であるのに対し、両方9000バイトでは1125MB/秒と、1.7倍以上に高速化される。むしろ、ジャンボフレームにしないと真価が発揮できない、という捉え方の方が正確だろう。
その一方でランダムアクセスの場合はそれほど大きな影響はない。特に4KiB Q1T1だとPC側を1500バイトにした方が高速だが、これはデータ量がジャンボフレームの半分に満たないためのオーバーヘッドだと思われる。
CPUが強ければどうでもいいのかなぁ